import * as fs from "fs"
import * as path from "path"
import { promisify } from "util"
import { UserApp, UserAppDetail } from "../interface"
import { getDocDir, getLoginUser } from "../config"
import { APIContext, LoginUser, RouterDecorator } from "f2e-server3"
import { validteUserApp } from "../validators/app"
import { API, DIR_TYPE, stringify } from "../common"
import { getProfile, updateProfile } from "./profile"
import dayjs from "dayjs"

const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)
const mkdir = promisify(fs.mkdir)
const rm = promisify(fs.rm)

export const hasAuthority = (loginUser: LoginUser, item: UserApp) => {
    return loginUser.username === item.createdBy || item.editors.includes(loginUser.username)
}
export const getAppDetail = async (loginUser: false | LoginUser, appId: number) => {
    const profile = await getProfile()
    const app = profile.apps.find(item => item.id === appId && (!loginUser || hasAuthority(loginUser, item)))
    if (!app) {
        return API.error("站点不存在")
    }
    const path_detail = path.join(getDocDir(), app.id + '', DIR_TYPE.PROFILE)
    if (!fs.existsSync(path_detail)) {
        return API.error("站点信息异常")
    }
    const detail: UserAppDetail = JSON.parse(await readFile(path_detail, "utf8"))
    return API.success({
        app, detail, path_detail
    })
}

export class ActionApp {
    /**
     * 新增站点
     */
    @RouterDecorator("api/create_app")
    async create_app(app: UserApp, ctx: APIContext) {
        const loginUser = getLoginUser(ctx)
        if (!loginUser) {
            return API.error("未登录")
        }
        const profile = await getProfile()
        const error = validteUserApp(app, profile.apps)
        if (error) {
            return API.error(error)
        }
        app.createdAt = app.updatedAt = dayjs().format("YYYY-MM-DD HH:mm:ss")
        app.createdBy = app.updatedBy = loginUser.username
        app.editors = [loginUser.username]
        app.id = profile.max_app_index++
        profile.apps.unshift(app)
        await updateProfile(profile)
        await mkdir(
            path.join(getDocDir(), app.id + '', DIR_TYPE.DOCS),
            { recursive: true }
        )
        await mkdir(
            path.join(getDocDir(), app.id + '', DIR_TYPE.FILES),
        )
        await writeFile(
            path.join(getDocDir(), app.id + '', DIR_TYPE.PROFILE),
            stringify({
                tree_max_index: 1,
                tree: [],
            } as UserAppDetail)
        )
        profile.apps = profile.apps.filter(item => hasAuthority(loginUser, item))
        return API.success({
            ...loginUser,
            ...profile,
        })
    }

    @RouterDecorator("api/update_app")
    async update_app(app: UserApp, ctx: APIContext) {
        const loginUser = getLoginUser(ctx)
        if (!loginUser) {
            return API.error("未登录")
        }
        const profile = await getProfile()
        const base = profile.apps.find(item => item.id === app.id && hasAuthority(loginUser, item))
        if (!base) {
            return API.error("站点不存在")
        }
        const error = validteUserApp(app, profile.apps)
        if (error) {
            return API.error(error)
        }
        Object.assign(base, app)
        base.updatedBy = loginUser.username
        base.updatedAt = dayjs().format("YYYY-MM-DD HH:mm:ss")
        await updateProfile(profile)
        return API.success({
            ...loginUser,
            ...profile,
        })
    }
    /**
     * 删除站点
     */
    @RouterDecorator("api/delete_app")
    async delete_app(app: Pick<UserApp, "id">, ctx: APIContext) {
        const loginUser = getLoginUser(ctx)
        const profile = await getProfile()
        const base = profile.apps.find(item => item.id === app.id && hasAuthority(loginUser, item))
        if (!base) {
            return API.error("站点不存在")
        }
        profile.apps = profile.apps.filter(item => item.id !== app.id)
        await updateProfile(profile)
        await rm(path.join(getDocDir(), base.id + ''), { recursive: true })
        return API.success({
            ...loginUser,
            ...profile,
        })
    }

    @RouterDecorator("api/app_detail")
    async app_detail(app: Pick<UserApp, "id">, ctx: APIContext) {
        const loginUser = getLoginUser(ctx)
        const res = await getAppDetail(loginUser, app.id)
        if (res.success) {
            return API.success(res.data.detail)
        } else {
            return API.error(res.message)
        }
    }

    @RouterDecorator("api/app_init")
    async app_init(app: { id: number; paths: string[] }, ctx: APIContext) {
        const loginUser = getLoginUser(ctx)
        const profile = await getProfile()
        const base = profile.apps.find(item => item.id === app.id && hasAuthority(loginUser, item))
        if (!base) {
            return API.error("站点不存在")
        }
        const path_map: Record<string, number> = {}
        const detail: UserAppDetail = {
            tree_max_index: 1,
            tree: [],
        }
        for (let t = 0; t < app.paths.length; t++) {
            const item = app.paths[t];
            const paths = item.split("/")
            let pathParent = paths[0]
            for (let i = 1; i < paths.length; i++) {
                const part = paths[i];
                const p = pathParent + "/" + part
                if (!path_map[p]) {
                    const id = detail.tree_max_index++
                    path_map[p] = id
                    detail.tree.push({
                        id,
                        title: part,
                        parentId: path_map[pathParent],
                    })
                    await writeFile(path.join(getDocDir(), app.id + '', DIR_TYPE.DOCS, id + '.md'), `# ${part}`)
                }
                pathParent = p
            }
        }

        await writeFile(
            path.join(getDocDir(), app.id + '', DIR_TYPE.PROFILE),
            stringify(detail)
        )
        return API.success({
            detail, path_map,
        })
    }
}
